package oktx.narayana;

import com.arjuna.ats.internal.jdbc.BaseTransactionalDriverXAConnection;
import com.arjuna.ats.internal.jdbc.ConnectionImple;
import com.arjuna.ats.internal.jdbc.TransactionalDriverXAConnection;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;
import java.util.Properties;

/**
 * Created by huangdachao on 2018/6/5 17:08.
 */
@SuppressWarnings("unchecked")
public class NarayanaConnection extends ConnectionImple {
    private volatile Date lastUseTime;
    private Field connectionField;
    private Field txConnectionField;

    public NarayanaConnection(String dbName, Properties info) throws SQLException {
        super(dbName, info);
        try {
            connectionField = ConnectionImple.class.getDeclaredField("_theConnection");
            txConnectionField = ConnectionImple.class.getDeclaredField("_transactionalDriverXAConnectionConnection");
            connectionField.setAccessible(true);
            txConnectionField.setAccessible(true);
        } catch (NoSuchFieldException | SecurityException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void incrementUseCount() {
        super.incrementUseCount();
        lastUseTime = new Date();
    }

    public Date getLastUseTime() {
        return lastUseTime;
    }

    public BaseTransactionalDriverXAConnection getConnectionControl() {
        try {
            return (BaseTransactionalDriverXAConnection) txConnectionField.get(this);
        } catch (IllegalAccessException e) {
            return null;
        }
    }

    public synchronized void closeCurrentConnection() { // 关闭时必须获取实例锁，防止当前连接正在分配。参考NarayanaConnectionManager Line77, Line104
        if (!inUse()) {
            try {
                Connection con = (Connection) connectionField.get(this);
                if (con != null) {
                    con.close();
                    connectionField.set(this, null);
                }
                TransactionalDriverXAConnection txCon = (TransactionalDriverXAConnection) txConnectionField.get(this);
                txCon.closeCloseCurrentConnection();
            } catch (IllegalAccessException | SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
